package com.v9.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.v9.common.core.service.DefaultService;
import com.v9.common.dto.TreeNodeDto;
import com.v9.common.utils.StringUtils;
import com.v9.common.utils.ValuePare;
import com.v9.system.domain.DeptInfo;
import com.v9.system.domain.UserInfo;
import com.v9.system.mapper.DeptInfoMapper;
import com.v9.system.service.DeptInfoService;
import com.v9.system.service.UserInfoService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 部门管理 服务实现
 *
 * @author shilun
 */
@Service
public class DeptInfoServiceImpl extends DefaultService<DeptInfoMapper, DeptInfo> implements DeptInfoService {
    @Override
    public String treeTypeCode() {
        return "dept";
    }

    @Override
    public String buildTreeTypeName() {
        return "部门树";
    }

    @Override
    public String buildTypeCode() {
        return "deptType";
    }

    @Override
    public String buildTypeName() {
        return "部门列表";
    }

    @Lazy
    @Resource
    private UserInfoService userInfoService;

    @Override
    public List<ValuePare> buildData() {
        List<ValuePare> results = new ArrayList<>();
        List<DeptInfo> roleInfos = queryAll();
        roleInfos.forEach(item -> {
            ValuePare pare = new ValuePare(item.getId(), item.getName());
            results.add(pare);
        });
        return results;
    }

    @Override
    public List<DeptInfo> querySubDeptListById(Long id) {
        DeptInfo byId = findById(id);
        String ids = "";
        if (byId.getIds() == null) {
            ids = String.valueOf(id);
        } else {
            ids = byId.getIds() + "|" + id;
        }
        QueryWrapper<DeptInfo> query = new QueryWrapper<>();
        query.likeRight("ids", ids);
        return query(query);
    }

    @Override
    public List<TreeNodeDto> deptUserTree() {
        return buildDeptUserData(null).getChildren();
    }

    private TreeNodeDto buildDeptUserData(TreeNodeDto parent) {
        if (parent == null) {
            TreeNodeDto roots = new TreeNodeDto();
            QueryWrapper<DeptInfo> query = new QueryWrapper<>();
            query.isNull("parent_id");
            query.orderByAsc("id");
            List<DeptInfo> departments = query(query);
            if (departments != null && departments.size() > 0) {
                roots.setChildren(new ArrayList<>());
            }
            departments.forEach(item -> {
                TreeNodeDto dto = new TreeNodeDto();
                dto.setId(item.getId().toString());
                dto.setSeq(item.getSeq());
                dto.setData(item);
                dto.setType(1);
                dto.setLabel(item.getName());
                roots.getChildren().add(dto);
                buildDeptUserData(dto);
            });
            return roots;
        }
        QueryWrapper<DeptInfo> query = new QueryWrapper<>();
        query.eq("parent_id", parent.getId());
        query.orderByAsc("id");
        List<DeptInfo> departments = this.query(query);
        if (departments != null && departments.size() > 1) {
            Collections.sort(departments, new Comparator<DeptInfo>() {
                @Override
                public int compare(DeptInfo o1, DeptInfo o2) {
                    if (o1.getSeq() > o2.getSeq()) {
                        return 1;
                    }
                    return 0;
                }
            });
        }
        if (departments != null && departments.size() > 0) {
            parent.setChildren(new ArrayList<>());
            departments.forEach(item -> {
                TreeNodeDto dto = new TreeNodeDto();
                dto.setParent(parent);
                dto.setId(item.getId().toString());
                dto.setData(item);
                dto.setType(1);
                dto.setSeq(item.getSeq());
                dto.setLabel(item.getName());
                parent.getChildren().add(dto);
                buildDeptUserData(dto);
            });
        }
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dept_id", parent.getId());
        List<UserInfo> users = userInfoService.query(queryWrapper);
        if (users != null && users.size() > 0) {
            if (parent.getChildren() == null) {
                parent.setChildren(new ArrayList<>());
            }
            users.forEach(item -> {
                TreeNodeDto dto = new TreeNodeDto();
                dto.setParent(parent);
                dto.setId(item.getId().toString());
                dto.setData(item);
                dto.setType(2);
                dto.setSeq(item.getSeq());
                dto.setLabel(item.getRealName());
                parent.getChildren().add(dto);
                buildData(dto);
            });
        }
        return parent;
    }

    public List<TreeNodeDto> queryTree(String name) {
        QueryWrapper<DeptInfo> query = new QueryWrapper<>();
        if (StringUtils.isNotBlank(name)) {
            query.like("name", name);
        } else {
            return buildTreeData();
        }
        List<DeptInfo> list = query(query);
        List<TreeNodeDto> result = new ArrayList<>();
        list.forEach(item -> {
            TreeNodeDto dto = new TreeNodeDto();
            dto.setSeq(item.getSeq());
            dto.setLabel(item.getName());
            dto.setData(item);
            dto.setValue(item.getName());
            dto.setId(item.getId().toString());
            buildData(dto);
            result.add(dto);
        });
        return result;
    }

    @Override
    public List<TreeNodeDto> buildTreeData() {
        return buildData(null).getChildren();
    }

    private TreeNodeDto buildData(TreeNodeDto parent) {
        if (parent == null) {
            TreeNodeDto roots = new TreeNodeDto();
            QueryWrapper<DeptInfo> query = new QueryWrapper<>();
            query.isNull("parent_id");
            query.orderByAsc("id");
            List<DeptInfo> departments = query(query);
            if (departments != null && departments.size() > 0) {
                roots.setChildren(new ArrayList<>());
            }
            departments.forEach(item -> {
                TreeNodeDto dto = new TreeNodeDto();
                dto.setId(item.getId().toString());
                dto.setSeq(item.getSeq());
                dto.setData(item);
                dto.setLabel(item.getName());
                roots.getChildren().add(dto);
                buildData(dto);
            });
            return roots;
        }
        QueryWrapper<DeptInfo> query = new QueryWrapper<>();
        query.eq("parent_id", parent.getId());
        query.orderByAsc("id");
        List<DeptInfo> departments = this.query(query);
        if (departments != null && departments.size() > 1) {
            Collections.sort(departments, new Comparator<DeptInfo>() {
                @Override
                public int compare(DeptInfo o1, DeptInfo o2) {
                    if (o1.getSeq() > o2.getSeq()) {
                        return 1;
                    }
                    return 0;
                }
            });
        }
        if (departments != null && departments.size() > 0) {
            parent.setChildren(new ArrayList<>());
            departments.forEach(item -> {
                TreeNodeDto dto = new TreeNodeDto();
                dto.setParent(parent);
                dto.setId(item.getId().toString());
                dto.setData(item);
                dto.setSeq(item.getSeq());
                dto.setLabel(item.getName());
                parent.getChildren().add(dto);
                buildData(dto);
            });
        }
        return parent;
    }
}
